fix(desktop): offer safe resume after completed tool timeout - #4075
fix(desktop): offer safe resume after completed tool timeout#4075liugddx wants to merge 4 commits into
Conversation
jackwener
left a comment
There was a problem hiding this comment.
I reviewed exact head 24d79cea01006c5994854702eb59653884b9a30b. I found one correctness issue in the new candidate rule.
[P2] Require every tool boundary to be settled before showing Safe Resume
latestInterruptedResumeTurnId() currently treats one completed tool as sufficient, even when another tool in the same failed Turn has no durable result. This is a normal persisted shape: after one successful tool, a later tool_call can time out before its tool_result is written. materializeTurns() then projects the two tools as [completed, interrupted], but the new .some(status === 'completed') check still returns the Turn ID and Desktop renders the Safe Resume action.
The Runtime planner correctly fails closed for the same boundary: the unmatched call becomes pending_tool_result / dangling_tool_state, so clicking the action only produces a parked recovery error. This makes Desktop promise a recovery path that its authority will reject, and it contradicts the PR description's statement that incomplete tools remain gated.
The new test does not cover the production shape. It checks a hand-built Turn containing only running, while an unfinished tool in a terminal Turn is projected as interrupted; it also never combines a completed tool with the unfinished one. Replacing the predicate with “at least one tool, and every tool is completed” left both new tests green, confirming that they do not distinguish the faulty rule.
Please gate the action on the whole tool set (or on an equally strict projection of the Runtime planner) and add a regression that goes through materializeTurns() with one completed tool plus one missing result. If a completed-plus-errored Turn should remain an inspection flow as the PR description says, the same all-completed rule also closes that mixed case.
Separately, this head now conflicts with current main after #4073 in app-shell-turn-view-model.ts and session-status-presentation.ts. Please rebase and preserve #4073's newer separation between the failure reason and execution-state copy. The exact-head hosted test check is green, and the local Desktop suite passed 1,629/1,629 tests; those checks do not remove the mixed-state defect above.
Posted by an automated review agent operated by @WAWQAQ. This is not an
independent human review and does not satisfy the committer review required by
CONTRIBUTING.md. A human is accountable for this comment — please push back if
anything here is wrong.
简体中文
本条评论由 @WAWQAQ 运行的自动化审查程序发出。它不构成 CONTRIBUTING.md
所要求的独立人类审查,也不能替代人类审查。有人类对本条评论负责,如有错误请直接指出。
24d79ce to
1eb6ab0
Compare
|
Addressed the review: timeout Safe Resume now requires a non-empty tool set where every tool is completed; mixed [completed, interrupted] and errored/incomplete tool states remain gated. Added a regression using materializeTurns() to cover the persisted mixed shape. Rebased onto current main (including #4073) and force-pushed; new head is 1eb6ab0. |
jackwener
left a comment
There was a problem hiding this comment.
I re-reviewed exact head 1eb6ab0067722378afb6c9f8fdd00c24340739da. The previous mixed-tool finding is fixed, and I found no remaining blocking issues.
The timeout recovery candidate now requires a non-empty tool set in which every rendered tool has a durable completed result. A persisted Turn with one completed tool followed by a call whose result never arrived materializes as [completed, interrupted] and is correctly excluded. Errored and running tools are excluded as well, while app_restarted keeps its existing recovery behavior. The Runtime resume planner remains the final authority when the action is used.
The new regression goes through materializeTurns() and reproduces the actual mixed persisted shape. As a falsification check, restoring the old some(completed) predicate made both mixed-state regressions fail; restoring the fix made them pass again. The complete Desktop suite passed locally (1,663/1,663), along with the full workspace test build, formatting, and diff checks.
This head is based directly on the current main; the previous conflicts with #4073 are gone and the merge result is clean. The exact-head hosted test check is successful.
Posted by an automated review agent operated by @WAWQAQ. This is not an
independent human review and does not satisfy the committer review required by
CONTRIBUTING.md. A human is accountable for this comment — please push back if
anything here is wrong.
简体中文
本条评论由 @WAWQAQ 运行的自动化审查程序发出。它不构成 CONTRIBUTING.md
所要求的独立人类审查,也不能替代人类审查。有人类对本条评论负责,如有错误请直接指出。
| const errorClass = latestTurn.errorClass?.toLowerCase(); | ||
| if (errorClass === 'app_restarted') return latestTurn.turnId; | ||
| if ( | ||
| errorClass?.includes('timeout') && |
There was a problem hiding this comment.
[P2] Do not offer timeout recovery when Safe Resume is disabled
Safe-boundary resume is off by default unless MAKA_RUNTIME_SAFE_BOUNDARY_RESUME=1 is set. I could not find a production Desktop startup path that enables it, but this branch now exposes the action for its normal target case: a timeout after completed tools. Clicking it in the default configuration always parks with resume_feature_disabled.
Runtime still fails closed, so this is not a safety problem. It is a UX problem: the button promises a recovery action that cannot run. Could we either hide it when the Runtime capability is disabled, or make enabling the capability part of this rollout?
简体中文
Safe Resume 默认关闭,只有设置 MAKA_RUNTIME_SAFE_BOUNDARY_RESUME=1 才能使用,但这里会在默认 Desktop 中为“工具已完成后超时”的情况显示恢复按钮。用户点击后只会得到 resume_feature_disabled。
Runtime 仍会安全地拒绝执行,所以这不是安全问题,但按钮在默认配置下无法完成它承诺的操作。可以在能力未开启时隐藏按钮,或者把开启该能力纳入这次发布。
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for tightening this up. I rechecked exact head 1eb6ab0067722378afb6c9f8fdd00c24340739da.
The earlier mixed-tool issue is fixed. The candidate now requires a non-empty tool set where every projected tool is completed, and the materializeTurns() regression covers the real [completed, interrupted] shape. Runtime Host still makes the final resume decision and fails closed if the durable boundary is not safe.
I left one non-blocking P2 inline about showing the timeout recovery action while Safe Resume is disabled. It does not allow an unsafe resume or create data risk, so I am approving with that comment.
The exact-head hosted test check is successful.
AI-assisted review: Codex coordinated an @reviewer pass. I checked the exact-head diff, the prior feedback, the Runtime authority, and the final severity. Astro-Han owns this approval decision.
简体中文
谢谢继续把这部分补完整。之前混合工具状态的问题已经修好:现在只有非空且全部完成的工具集合才会成为候选,materializeTurns() 测试也覆盖了真实的 [completed, interrupted] 投影。最终是否能够恢复仍由 Runtime Host 判断,不安全时会直接拒绝。
我在行内留了一个不阻塞的 P2,内容是 Safe Resume 未开启时仍会显示 timeout 恢复按钮。这个问题不会绕过 Runtime,也没有数据风险,因此我带着这条评论批准。
当前 head 的托管 test 已通过。
Summary
Scope
This is the first Desktop recovery slice for #4074. It does not change Runtime tool execution, does not re-run tools, and does not change the
MAKA_RUNTIME_SAFE_BOUNDARY_RESUMErollout flag. The existingturn.resume.query/startplanner remains the authority for whether continuation may actually start.Related: #4074
Validation
npm --workspace @maka/desktop run typechecknpm --workspace @maka/desktop run build:mainnode --test "dist/main/__tests__/session-status-presentation.test.js" "dist/main/__tests__/interrupted-resume.test.js"npx biome checkon changed files